﻿// Type: VSFile.VisualStudioFiles
// Assembly: VSFile, Version=1.2.1.0, Culture=neutral, PublicKeyToken=null
// Assembly location: C:\Downloads\VSFile.dll

using System;
using System.Collections.Generic;
using System.IO;

namespace ReadSolutionContents
{
    /// <summary>
    /// Manages multiple Visual Studio files of varying type.
    /// 
    /// </summary>
    public class VisualStudioFiles
    {
        /// <summary>
        /// Supported file extensions.
        /// 
        /// </summary>
        private static readonly string[] SupportedExtensions = new string[7]
    {
      ".vbproj",
      ".vb",
      ".csproj",
      ".cs",
      ".fsproj",
      ".fs",
      ".sln"
    };
        /// <summary>
        /// Initialized Visual Basic project files.
        /// 
        /// </summary>
        private List<BasicProjectFile> m_basicProjectFiles;
        /// <summary>
        /// Initialized Visual Basic source files.
        /// 
        /// </summary>
        private List<BasicSourceFile> m_basicSourceFiles;
        /// <summary>
        /// Initialized Visual C# project files.
        /// 
        /// </summary>
        private List<CSharpProjectFile> m_cSharpProjectFiles;
        /// <summary>
        /// Initialized Visual C# source files.
        /// 
        /// </summary>
        private List<CSharpSourceFile> m_cSharpSourceFiles;
        /// <summary>
        /// Initialized Visual F# project files.
        /// 
        /// </summary>
        private List<FSharpProjectFile> m_fSharpProjectFiles;
        /// <summary>
        /// Initialized Visual F# source files.
        /// 
        /// </summary>
        private List<FSharpSourceFile> m_fSharpSourceFiles;
        /// <summary>
        /// Option to use when searching for files.
        /// 
        /// </summary>
        private SearchOption m_fileSearchOption;
        /// <summary>
        /// Initialized Visual Studio solution files.
        /// 
        /// </summary>
        private List<SolutionFile> m_solutionFiles;

        /// <summary>
        /// Get initialized Visual Basic project files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of BasicProjectFile objects representing
        ///             initialized Visual Basic project files.
        /// 
        /// </value>
        public IEnumerable<BasicProjectFile> BasicProjectFiles
        {
            get
            {
                return (IEnumerable<BasicProjectFile>)this.m_basicProjectFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual Basic source files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of BasicSourceFile objects representing
        ///             initialized Visual Basic source files.
        /// 
        /// </value>
        public IEnumerable<BasicSourceFile> BasicSourceFiles
        {
            get
            {
                return (IEnumerable<BasicSourceFile>)this.m_basicSourceFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual C# project files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of CSharpProjectFile objects representing
        ///             initialized Visual C# project files.
        /// 
        /// </value>
        public IEnumerable<CSharpProjectFile> CSharpProjectFiles
        {
            get
            {
                return (IEnumerable<CSharpProjectFile>)this.m_cSharpProjectFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual C# source files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of CSharpSourceFile objects representing
        ///             initialized Visual C# source files.
        /// 
        /// </value>
        public IEnumerable<CSharpSourceFile> CSharpSourceFiles
        {
            get
            {
                return (IEnumerable<CSharpSourceFile>)this.m_cSharpSourceFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual F# project files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of FSharpProjectFile objects representing
        ///             initialized Visual F# project files.
        /// 
        /// </value>
        public IEnumerable<FSharpProjectFile> FSharpProjectFiles
        {
            get
            {
                return (IEnumerable<FSharpProjectFile>)this.m_fSharpProjectFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual F# source files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of FSharpSourceFile objects representing
        ///             initialized Visual F# source files.
        /// 
        /// </value>
        public IEnumerable<FSharpSourceFile> FSharpSourceFiles
        {
            get
            {
                return (IEnumerable<FSharpSourceFile>)this.m_fSharpSourceFiles;
            }
        }

        /// <summary>
        /// Get initialized Visual Studio solution files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// Enumerable collection of SolutionFile objects representing
        ///             initialized Visual Studio solution files.
        /// 
        /// </value>
        public IEnumerable<SolutionFile> SolutionFiles
        {
            get
            {
                return (IEnumerable<SolutionFile>)this.m_solutionFiles;
            }
        }

        /// <summary>
        /// Get option to use when searching for files.
        /// 
        /// </summary>
        /// 
        /// <value>
        /// SearchOption enumeration value specifying whether to search all
        ///             subdirectories for files or only current directory.
        /// 
        /// </value>
        private SearchOption FileSearchOption
        {
            get
            {
                return this.m_fileSearchOption;
            }
        }

        static VisualStudioFiles()
        {
        }

        /// <summary>
        /// Constructor for specifying file paths.
        /// 
        /// </summary>
        /// <param name="filePaths">Enumerable collection of strings representing file paths.
        ///             </param>
        public VisualStudioFiles(IEnumerable<string> filePaths)
            : this(filePaths, false)
        {
        }

        /// <summary>
        /// Constructor for specifying recursive search option.
        /// 
        /// </summary>
        /// <param name="filePaths">Enumerable collection of strings representing file paths.
        ///             </param><param name="recursiveSearch">True if all subdirectories in given file paths are also to be
        ///             searched, false otherwise.
        ///             </param>
        public VisualStudioFiles(IEnumerable<string> filePaths, bool recursiveSearch)
        {
            this.m_basicProjectFiles = new List<BasicProjectFile>();
            this.m_basicSourceFiles = new List<BasicSourceFile>();
            this.m_cSharpProjectFiles = new List<CSharpProjectFile>();
            this.m_cSharpSourceFiles = new List<CSharpSourceFile>();
            this.m_fSharpProjectFiles = new List<FSharpProjectFile>();
            this.m_fSharpSourceFiles = new List<FSharpSourceFile>();
            this.m_fileSearchOption = recursiveSearch ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
            this.m_solutionFiles = new List<SolutionFile>();
            this.Initialize(filePaths);
        }

        /// <summary>
        /// Initialize Visual Studio files at given paths.
        /// 
        /// </summary>
        /// <param name="filePaths">Enumerable collection of strings representing file paths.
        ///             </param>
        private void Initialize(IEnumerable<string> filePaths)
        {
            if (filePaths == null)
                throw new ArgumentNullException();
            foreach (string filePath in filePaths)
                this.Initialize(filePath);
        }

        /// <summary>
        /// Initialize file at given path.
        /// 
        /// </summary>
        /// <param name="filePath">String representing file path.
        ///             </param>
        private void Initialize(string filePath)
        {
            string str = Path.GetDirectoryName(filePath);
            if (string.IsNullOrEmpty(str))
                str = Directory.GetCurrentDirectory();
            if (Wildcard.HasWildcard(str))
                return;
            string fileName = Path.GetFileName(filePath);
            if (Wildcard.HasWildcard(fileName))
            {
                this.Initialize((IEnumerable<string>)Directory.GetFiles(str, fileName, this.FileSearchOption));
            }
            else
            {
                string fileExtension = Path.GetExtension(filePath).ToLowerInvariant();
                if (!VisualStudioFiles.IsSupportedExtension(fileExtension))
                    return;
                this.Initialize(filePath, fileExtension);
            }
        }

        /// <summary>
        /// Initialize file at given path with given supported extension.
        /// 
        /// </summary>
        /// <param name="filePath">String representing file path.
        ///             </param><param name="fileExtension">String representing supported file extension.
        ///             </param>
        private void Initialize(string filePath, string fileExtension)
        {
            switch (fileExtension)
            {
                case ".vbproj":
                    this.m_basicProjectFiles.Add(new BasicProjectFile(filePath));
                    break;
                case ".vb":
                    this.m_basicSourceFiles.Add(new BasicSourceFile(filePath));
                    break;
                case ".csproj":
                    this.m_cSharpProjectFiles.Add(new CSharpProjectFile(filePath));
                    break;
                case ".cs":
                    this.m_cSharpSourceFiles.Add(new CSharpSourceFile(filePath));
                    break;
                case ".fsproj":
                    this.m_fSharpProjectFiles.Add(new FSharpProjectFile(filePath));
                    break;
                case ".fs":
                    this.m_fSharpSourceFiles.Add(new FSharpSourceFile(filePath));
                    break;
                case ".sln":
                    this.m_solutionFiles.Add(new SolutionFile(filePath));
                    break;
            }
        }

        /// <summary>
        /// Determine if given file extension is supported.
        /// 
        /// </summary>
        /// <param name="fileExtension">String representing file extension.
        ///             </param>
        /// <returns>
        /// True if file extension is supported, false otherwise.
        /// 
        /// </returns>
        private static bool IsSupportedExtension(string fileExtension)
        {
            if (!string.IsNullOrEmpty(fileExtension))
            {
                foreach (string str in VisualStudioFiles.SupportedExtensions)
                {
                    if (fileExtension.Equals(str, StringComparison.CurrentCultureIgnoreCase))
                        return true;
                }
            }
            return false;
        }
    }
}
